﻿using MathGraphics;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TileMap;

namespace TestForm
{
    public partial class Form1 : Form
    {
        private Size _sizeMatrix = new Size(6, 6);
        private Size _resolution = new Size(2560, 1920);
        private BitmapMatrix _matrix = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void tbRows_Validating(object sender, CancelEventArgs e)
        {
            if (!_isClosing)
            {
                string content = tbRows.Text;
                uint rows = 0;
                e.Cancel = !uint.TryParse(content, out rows);
                if (!e.Cancel)
                {
                    _sizeMatrix.Width = (int)rows;
                }
                else
                {
                    MessageBox.Show("数值无效，请重新输入！");
                }
            }
        }

        private void tbCols_Validating(object sender, CancelEventArgs e)
        {
            if (!_isClosing)
            {
                string content = tbCols.Text;
                uint cols = 0;
                e.Cancel = !uint.TryParse(content, out cols);
                if (!e.Cancel)
                {
                    _sizeMatrix.Height = (int)cols;
                }
                else
                {
                    MessageBox.Show("数值无效，请重新输入！");
                }
            }
        }

        private bool _isClosing = false;
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            _isClosing = true;
        }

        private void tbResolution_Validating(object sender, CancelEventArgs e)
        {
            if (!_isClosing)
            {
                string[] strs = tbResolution.Text.Split('*');
                if (strs.Length != 2)
                {
                    e.Cancel = true;
                    MessageBox.Show("数值无效，请重新输入！");
                    return;
                }
                uint w = 0;
                uint h = 0;
                if (!uint.TryParse(strs[0], out w))
                {
                    e.Cancel = true;
                    MessageBox.Show("数值无效，请重新输入！");
                    return;
                }
                if (!uint.TryParse(strs[1], out h))
                {
                    e.Cancel = true;
                    MessageBox.Show("数值无效，请重新输入！");
                    return;
                }
                _resolution = new Size((int)w, (int)h);
            }
        }

        private async void btnCreate_Click(object sender, EventArgs e)
        {
            _matrix = await Task.Factory.StartNew(() =>
            {
                if (_matrix != null)
                    _matrix.Dispose();
                return new BitmapMatrix(_sizeMatrix.Width, _sizeMatrix.Height, _resolution , System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            });
            MessageBox.Show("创建成功！" + _matrix);
            btnDraw.Enabled = true;
            btnSave.Enabled = true;
            AdjustMatrixTable();
            tableMatrix.Invalidate();
        }

        private void AdjustMatrixTable()
        {
            tableMatrix.RowCount = _sizeMatrix.Width;
            tableMatrix.RowStyles.Clear();
            float height = 1f / _sizeMatrix.Height * 100;
            for (int i = 0; i < tableMatrix.RowCount; i++)
            {
                var index = tableMatrix.RowStyles.Add(new RowStyle(SizeType.Percent, height));
            }

            tableMatrix.ColumnCount = _sizeMatrix.Height;
            tableMatrix.ColumnStyles.Clear();
            float width = 1f / _sizeMatrix.Width * 100;
            for (int i = 0; i < tableMatrix.ColumnCount; i++)
            {
                tableMatrix.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, width));
            }
        }
        
        private void btnDraw_Click(object sender, EventArgs e)
        {
            if (_matrix == null)
            {
                return;
            }
            Clear(Color.White);
            DateTime dtStart = DateTime.Now;
            PaintCircles();
            MessageBox.Show(string.Format("耗时{0}", (DateTime.Now - dtStart).TotalMilliseconds.ToString()));
            tableMatrix.Invalidate();
        }

        private void Clear(Color color)
        {
            for (int i = 0; i < _matrix.Rows; i++)
            {
                for (int j = 0; j < _matrix.Columns; j++)
                {
                    using (Graphics g = _matrix.CreateGraphics(i, j))
                    {
                        g.Clear(color);
                    }
                }
            }
        }

        private Pen pen = new Pen(Color.Red, 5.0f);
        private Point _currentCell = Point.Empty;
        private void PaintCircles()
        {
            Size resolution = _matrix.Resolution;
            Circle cirlce = new Circle(Point.Empty, 50);
            float interval = 150;
            Graphics[,] gMatrix = new Graphics[_matrix.Columns, _matrix.Rows];
            for (int i = 0; i < _matrix.Rows; i++)
            {
                for (int j = 0; j < _matrix.Columns; j++)
                {
                    gMatrix[j, i] = _matrix.CreateGraphics(j, i);
                }
            }
            Size sizeBase;
            while (cirlce.Y < resolution.Height)
            {
                while (cirlce.X < resolution.Width)
                {
                    Point cell = new Point((int)cirlce.X / _matrix.SingleResolution.Width, ((int)cirlce.Y / _matrix.SingleResolution.Height));
                    sizeBase = new Size(cell.X * _matrix.SingleResolution.Width, cell.Y * _matrix.SingleResolution.Height);
                    gMatrix[cell.X, cell.Y].DrawEllipse(pen, new RectangleF(cirlce.X - sizeBase.Width - cirlce.Radius, cirlce.Y - sizeBase.Height - cirlce.Radius, cirlce.Radius * 2, cirlce.Radius * 2));
                    float leftDis = cirlce.X - sizeBase.Width;
                    float rightDis = sizeBase.Width + _matrix.SingleResolution.Width - cirlce.X;
                    float topDis = cirlce.Y - sizeBase.Height;
                    float buttomDis = sizeBase.Height + _matrix.SingleResolution.Height - cirlce.Y;

                    if (leftDis < cirlce.Radius && cell.X >= 1)
                    {
                        sizeBase = new Size((cell.X - 1) * _matrix.SingleResolution.Width, cell.Y * _matrix.SingleResolution.Height);
                        gMatrix[cell.X - 1, cell.Y].DrawEllipse(pen, new RectangleF(cirlce.X - sizeBase.Width - cirlce.Radius, cirlce.Y - sizeBase.Height - cirlce.Radius, cirlce.Radius * 2, cirlce.Radius * 2));
                    }
                    if (topDis < cirlce.Radius && cell.Y >= 1)
                    {
                        sizeBase = new Size(cell.X * _matrix.SingleResolution.Width, (cell.Y - 1) * _matrix.SingleResolution.Height);
                        gMatrix[cell.X, cell.Y - 1].DrawEllipse(pen, new RectangleF(cirlce.X - sizeBase.Width - cirlce.Radius, cirlce.Y - sizeBase.Height - cirlce.Radius, cirlce.Radius * 2, cirlce.Radius * 2));
                    }

                    if (buttomDis < cirlce.Radius && cell.Y < _matrix.Columns - 1)
                    {
                        sizeBase = new Size(cell.X * _matrix.SingleResolution.Width, (cell.Y + 1) * _matrix.SingleResolution.Height);
                        gMatrix[cell.X, cell.Y + 1].DrawEllipse(pen, new RectangleF(cirlce.X - sizeBase.Width - cirlce.Radius, cirlce.Y - sizeBase.Height - cirlce.Radius, cirlce.Radius * 2, cirlce.Radius * 2));
                    }
                    if (rightDis < cirlce.Radius && cell.X < _matrix.Rows - 1)
                    {
                        sizeBase = new Size((cell.X + 1) * _matrix.SingleResolution.Width, cell.Y * _matrix.SingleResolution.Height);
                        gMatrix[cell.X + 1, cell.Y].DrawEllipse(pen, new RectangleF(cirlce.X - sizeBase.Width - cirlce.Radius, cirlce.Y - sizeBase.Height - cirlce.Radius, cirlce.Radius * 2, cirlce.Radius * 2));
                    }

                    if (leftDis < cirlce.Radius && topDis < cirlce.Radius && cell.X >= 1 && cell.Y >= 1)
                    {
                        sizeBase = new Size((cell.X - 1) * _matrix.SingleResolution.Width, (cell.Y - 1) * _matrix.SingleResolution.Height);
                        gMatrix[cell.X - 1, cell.Y - 1].DrawEllipse(pen, new RectangleF(cirlce.X - sizeBase.Width - cirlce.Radius, cirlce.Y - sizeBase.Height - cirlce.Radius, cirlce.Radius * 2, cirlce.Radius * 2));
                    }
                    if (leftDis < cirlce.Radius && buttomDis < cirlce.Radius && cell.X >= 1 && cell.Y < _matrix.Columns - 1)
                    {
                        sizeBase = new Size((cell.X - 1) * _matrix.SingleResolution.Width, (cell.Y + 1) * _matrix.SingleResolution.Height);
                        gMatrix[cell.X - 1, cell.Y + 1].DrawEllipse(pen, new RectangleF(cirlce.X - sizeBase.Width - cirlce.Radius, cirlce.Y - sizeBase.Height - cirlce.Radius, cirlce.Radius * 2, cirlce.Radius * 2));
                    }
                    if (rightDis < cirlce.Radius && cell.X < _matrix.Rows - 1 && topDis < cirlce.Radius && cell.Y >= 1)
                    {
                        sizeBase = new Size((cell.X + 1) * _matrix.SingleResolution.Width, (cell.Y - 1) * _matrix.SingleResolution.Height);
                        gMatrix[cell.X + 1, cell.Y - 1].DrawEllipse(pen, new RectangleF(cirlce.X - sizeBase.Width - cirlce.Radius, cirlce.Y - sizeBase.Height - cirlce.Radius, cirlce.Radius * 2, cirlce.Radius * 2));
                    }
                    if (rightDis < cirlce.Radius && cell.X < _matrix.Rows - 1 && buttomDis < cirlce.Radius && cell.Y < _matrix.Columns - 1)
                    {
                        sizeBase = new Size((cell.X + 1) * _matrix.SingleResolution.Width, (cell.Y + 1) * _matrix.SingleResolution.Height);
                        gMatrix[cell.X + 1, cell.Y + 1].DrawEllipse(pen, new RectangleF(cirlce.X - sizeBase.Width - cirlce.Radius, cirlce.Y - sizeBase.Height - cirlce.Radius, cirlce.Radius * 2, cirlce.Radius * 2));
                    }

                    cirlce.X += interval;
                }
                cirlce.Y += interval;
                cirlce.X = 0;
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (_matrix == null)
            {
                return;
            }
            using (FolderBrowserDialog dialog = new FolderBrowserDialog())
            {
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    _matrix.Save(dialog.SelectedPath);
                }
            }
        }

        private void tableMatrix_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
        {
            if (_matrix == null)
            {
                return;
            }
            Bitmap bmp = _matrix[e.Column, e.Row];
            if (bmp  == null)
            {
                return;
            }
            e.Graphics.DrawImage(bmp, e.CellBounds, new Rectangle(Point.Empty, bmp.Size), GraphicsUnit.Pixel);
        }
    }
}
